想JRA一样,JFR中也包含了两大部分,分别是内建于JRockit JVM的记录引擎和内建于JRockit Mission Control客户端的分析记录分析工具。记录引擎用于生成可供分析工具处理的记录文件,分析文件时,并不要求必须有活动连接,其本身是自描述的,即文件本身就包含了所有相关的元数据。此外,该文件也可以被发送给其他第3方分析工具做进一步的详细分析。
在本章中,JFR和JFA表示同一个意思,可以互换使用。
在JFR中,记录文件不再使用XML格式,所有内容均记录在内存缓冲区中,并辅以相应的时间戳,并在合适的时机将之写入到构成记录的二进制文件中,此外,还通过专门的Java API实现了自定义事件和自定义用户分析接口的功能。
在第8章中曾经提到过,JRA的记录是以XML格式存储的,其记录文件的后缀名为
.jra
。而在JFR中,文件后缀名变成了.jfr
,存储格式也改成了二进制格式。由于可能会产生大量的目标事件,因此需要避免不必要的开销,将数据压缩存储。JRA记录无法向前兼容,JFR也无法打开JRA的记录文件。
正如前面介绍的,在JFR中,事件就是在某个具体的时间点记录下的数据。
其中,事件包含一下种类型:
JFR中记录的事件由记录生成器产生,记录生成器定义了事件的具体类型。事件类型中包含了用于描述该类型本身信息的元数据。这些元数据中包含了该事件本身所包含的属性信息、属性的类型信息和属性的具体描述信息。JFR的记录文件中都包含了对该事件生成器的描述信息。
JRockit JVM作为其中一种事件生成器,优势巨大,它可以以较小的运行时代价,很方便的记录下运行时需要收集的事件信息。此外,用户可以通过调用相关的Java API,在JRockit JVM创建的底层事件上附加额外的上下文属性。
记录引擎(recording engine,有时也称为记录代理),内建于JVM之中,针对事件生成做了大量优化以完成相关任务,这些任务其中包括:
System.currentTimeMillis()
方法获取系统时间的具有不小的执行开销。因此,记录引擎为记录时间戳而提供了一个高度优化的本地时间版本。由于JRockit R28是作为补丁版本发布的,因此若是默认开启事件记录可能会带来一些麻烦。故而决定在启动JVM时,并不会立即启动记录引擎。其实在设计之初,记录引擎和JRockit JVM事件发生源就是放在一起考虑的,在开发测试过程中,也都是放在一起的(即便是做压力测试时,也不例外)。在将来的JRockit版本中,可能会对记录引擎做一些改动。
对于正在执行的事件记录而言,都会有一个ID和名字,其中ID具有唯一性。记录ID会在创建记录时设置,用于标识当前的记录。例如,可以在JRCMD中,通过记录ID来引用某个事件记录。
在启动JRockit时,附加以下命令行参数,即可启用JFR事件记录:
-XX:FlightRecorderOptions=defaultrecording=true
使用上面的命令行参数,可以创建一个ID为0,名字为JRockit default
的事件记录。
JFR中可以同时存在多个事件记录。如果同时有多个事件记录处于 活跃(live)状态,则在记录的时候,会将各自的事件类型进行聚合,并根据预设的阈值进行过滤。对于刚刚接触JFR的用户来说,这可能会带来一些困扰,而实际上,确实有可能出现记录的事件比期望的多的情况。
通过修改默认记录的事件设置选项(event settings)可以对记录引擎做详细配置,或者使用不同的配置开启一个新的记录。如果想要过滤掉多余的记录信息,请修改相关配置。
有多种方式可用于对记录引擎的方方面面进行配置,不过其中的某些方式只能在以命令行启动JVM时使用。
有两个主要的命令行参数用于对JFR进行配置。其一是用于控制是否开启JFR的命令行参数:
-XX:[+|-]FlightRecorder
其二是用于控制JFR运行行为:
-XX:FlightRecorderOptions=parameter1=value1[,parameter2=value2]
可用参数如下:
Parameter Description
settings=[name|filepath] 在服务器端载入额外的配置模板。默认情况下,配置模板存在于 **JROCKIT_HOME/jre/lib/jfr**路径下。
repository=[dir] JFR记录数据的路径,可看作是JFR的临时目录。默认情况下,存放于java.io.tmpdir属性定义的目录下,子目录的名字格式为 **yyyy_mm_dd_hh_mm_ss_pid**。例如,若进程号为4711,则创建的临时目录的名字为 **2010_04_21_16_28_59_4711**。
threadbuffersize=[size] 指定线程局部缓冲区(Thread Local Buffer)的大小,默认值为5KB。
globalbuffersize=[size] 指定全局局部缓冲区(Global Local Buffer)的大小,默认值为64KB。
numglobalbuffers=[num] 指定全局局部缓冲区(Global Local Buffer)的数量,默认值为8。
maxchunksize=[size] 指定存储的单个数据块的大小,默认值为12MB。
continuous=[true|false] 指定是否启用默认的连续记录,即使用记录ID0进行连续记录。无论该值设置为true还是false,只要启用了JFR,都可以通过JRockit Mission Control来开启连续记录。正如前文提到了,在JRockit R28中,禁用了默认记录,不过在将来的版本中可能会将之开启。
disk=[true|false] 指定是否将数据记录到硬盘中。默认为false,即会循环使用内存空间的记录区域。通过JRockit Mission Control或JRCMD,可以手动将记录内容刷入到硬盘中。
maxage=[nanotime] 指定数据在硬盘上保留的最长时间,单位为纳秒,默认值为0,即保留所有数据。
maxsize=[size] 指定最大保留多少数据,默认值为0,即保留所有数据。
无论是使用JRCMD还是命令参数,指定的参数选项都会通过模板文件以JSON格式被记录下来。JRockit发行版中附带了几个实例模板,位于JROCKIT_HOME/jre/lib/jfr
目录下。这些模板就是所谓的服务器端模板(server-side templates),因所使用的JRockit Mission Control客户端不同而有所区别。基于这些模板,用户可以根据实际需要开发定制话的模板。
有关服务器端模板的详细内容超出了本书的范畴,这里不再赘述。在第11章中将会在如何使用JRCMD来控制记录的生命周期。
与JRA类似,JFR也可以通过命令行参数来开启有时间限制的记录。在JFR中,命令行参数-XX:StartFlightRecording
可用于对执行时间做相关设置,例如,可以推迟记录的执行时间以便可以跳过JVM的阶段。下面的示例中,JFR会在JVM启动2分钟后再开始记录,记录持续一分钟,记录名为 MyRecording,并将结果存储到 c:\tmp\myrecording.jfr中。当然,这里也可以使用服务器端模板,通过名字引用即可,在示例中使用模板文件的是 profile.jfs。
-XX:StartFlightRecording=delay=120s,duration=60s,name=MyRecording,filename=C:\tmp\myrecording.jfr,settings=profile
更多有关命令行参数
StartFlightRecording
选项的内容,请参见JRockitR2的相关手册。
本章的剩余部分将着重介绍如何通过JRockit Mission Control客户端来控制JFR。